# coding=utf-8
# -*- coding: UTF-8 -*-
#
# This file is part of the kernelstudio package.
#
# (c) 2014-2025 zlin <admin@kernelstudio.com>
#
# For the full copyright and license information, please view the LICENSE file
# that was distributed with this source code.
import hashlib
import uuid

from flask import request

from ksai.persistence.storage.attachment import Attachment
from ksai.persistence.storage.events import app_storage_file_post_saved, app_storage_file_pre_saved
from ksai.persistence.storage.factory import storage
from ksai.utils import datetimes as dt
from ksai.web import exceptions


class AttachmentUploader:

    @staticmethod
    def upload(param_name="file", channel: str = "", category: str = "") -> Attachment:
        if param_name not in request.files:
            raise exceptions.UploadFileRequiredException()

        if len(request.files) > 1:
            raise exceptions.UploadTooManyFilesException()

        file = request.files[param_name]

        if not file.filename:
            raise exceptions.UploadFilenameRequiredException()

        content = file.stream.read()
        sign = hashlib.md5(content).hexdigest()
        file_uuid = str(uuid.uuid4())
        suffix = file.filename.split(".")[-1].lower()
        filename = file_uuid + '.' + suffix

        if category:
            category = category.lstrip('/')
            if category:
                category = '/' + category
        else:
            category = ""

        prefix = category + "/" + str(dt.year()) + '/' + str(dt.month()) + '/' + str(dt.day())
        filepath = prefix + '/' + filename

        attachment = Attachment(
            uuid=file_uuid,
            sign=sign,
            filepath=filepath,
            filename=filename,
            original_name=file.filename,
            size=len(content),
            mime=file.mimetype,
            suffix=suffix,
            category=category,
            channel=channel,
            content=content
        )

        app_storage_file_pre_saved.send(attachment)

        if not storage.save(filepath, content):
            raise exceptions.UploadPersistenceException()

        try:
            file.stream.close()
        except IOError:
            pass

        app_storage_file_post_saved.send(attachment)

        return attachment
